//
// Created by kenny on 25-10-20.
//
#include "mcp_net_mgr.h"
#include "mcp_logger.h"
#include <string.h>

#ifdef _WIN32
    #include <windows.h>
#else
    #include <unistd.h>
    #include <pthread.h>
#endif

int mcp_net_init(mcp_net_t* manager,
                        void (*recv_cb)(uint8_t* data, uint16_t length),
                        void (*udp_recv_cb)(uint8_t* data, uint16_t length,
                        const char* from_ip, int from_port),
                        void (*status_cb)(bool connected, const char* reason)) {
    if (!manager) return -1;

    memset(manager, 0, sizeof(mcp_net_t));
    manager->current_type = CONNECTION_TYPE_NONE;

    manager->recv_callback = recv_cb;
    manager->udp_recv_callback = udp_recv_cb;
    manager->status_callback = status_cb;
    return 0;
}

/**
 * 启动ＴＣＰ　连接
 * @param manager
 * @param ip
 * @param port
 * @return
 */
int mcp_net_connect_tcp(mcp_net_t* manager, const char* ip, int port) {
    if (!manager || !ip) return -1;

    // 先关闭当前连接
    mcp_net_close(manager);
    manager->current_type = CONNECTION_TYPE_TCP;

    // 初始化TCP管理器
    if (mcp_tcp_init(&manager->tcp_manager, ip, port,
                               manager->recv_callback,
                               manager->status_callback) != 0) {
        LOG_ERROR("Failed to initialize TCP manager");
        return -1;
    }

    // 连接TCP
    if (mcp_tcp_connect(&manager->tcp_manager) != 0) {
        LOG_ERROR("Failed to connect via TCP");
        return -1;
    }

    LOG_INFO("Connected via TCP to %s:%d", ip, port);

    return 0;
}

int mcp_net_connect_udp(mcp_net_t* manager, const char* ip, int port) {
    if (!manager || !ip) return -1;
    // 先关闭当前连接
    mcp_net_close(manager);

    // 初始化UDP管理器
    if (mcp_udp_init(&manager->udp_manager, ip, port,
                               manager->udp_recv_callback) != 0) {
        LOG_ERROR("Failed to initialize UDP manager");
        return -1;
    }
    LOG_DEBUG("3");
    // 连接UDP
    if (mcp_udp_connect(&manager->udp_manager) != 0) {
        LOG_ERROR("Failed to setup UDP socket");
        return -1;
    }
    LOG_DEBUG("4");
    manager->current_type = CONNECTION_TYPE_UDP;
    LOG_INFO("Setup UDP socket for %s:%d", ip, port);
    return 0;
}

int mcp_net_send(mcp_net_t* manager, const uint8_t* data, uint16_t length) {
    if (!manager || !data || length == 0) return -1;


    switch (manager->current_type) {
        case CONNECTION_TYPE_TCP:
            return mcp_tcp_send(&manager->tcp_manager, data, length);

        case CONNECTION_TYPE_UDP:
            return mcp_udp_send(&manager->udp_manager, data, length);

        default:
            LOG_WARN("No active connection");
            return -1;
    }
}

int mcp_net_send_udp_to(mcp_net_t* manager, const uint8_t* data, uint16_t length,
                               const char* dest_ip, int dest_port) {
    if (!manager || manager->current_type != CONNECTION_TYPE_UDP) {
        LOG_WARN("UDP send_to requires active UDP connection");
        return -1;
    }

    return mcp_udp_send_to(&manager->udp_manager, data, length, dest_ip, dest_port);
}

int mcp_net_close(mcp_net_t* manager) {
    if (!manager) return -1;
    switch (manager->current_type) {
        case CONNECTION_TYPE_TCP:
            mcp_tcp_close(&manager->tcp_manager);
            break;

        case CONNECTION_TYPE_UDP:
            mcp_udp_close(&manager->udp_manager);
            break;

        default:
            break;
    }

    manager->current_type = CONNECTION_TYPE_NONE;
    return 0;
}

/**
 * 网络判态是否已连接
 * @param manager
 * @return
 */
bool mcp_net_is_connected(mcp_net_t* manager) {
    if (!manager) return false;

    switch (manager->current_type) {
        case CONNECTION_TYPE_TCP:
            return mcp_tcp_is_connected(&manager->tcp_manager);

        case CONNECTION_TYPE_UDP:
            return mcp_udp_is_connected(&manager->udp_manager);

        default:
            return false;
    }
}

connection_type_t mcp_net_get_current_type(mcp_net_t* manager) {
    return manager ? manager->current_type : CONNECTION_TYPE_NONE;
}

void mcp_net_cleanup(mcp_net_t* manager) {
    if (!manager) return;

    mcp_net_close(manager);

    // 清理TCP资源
    mcp_tcp_cleanup(&manager->tcp_manager);

    // 清理UDP资源
    mcp_udp_cleanup(&manager->udp_manager);

    manager->current_type = CONNECTION_TYPE_NONE;
}